/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_ui.htm
 *
 * Zhiqim UI is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
 
+(function(Z)
{//BEGIN

Z.Input = Z.Class.newInstance();
//定义支持的类型数值的,整数,小数的,字母的,两位小数金额的,折扣值,小时分钟值
Z.Input.types = ["Numeric", "Alphabetic", "AlphaNumeric", "Integer", "Decimal", "Amount2R", "Discount", "Date", "HourMinute"];
Z.Input.prototype = 
{
    defaults:
    {
        elem: null,
        options: null
    },
    
    init: function()
    {//初始化
        if (!this.elem || !this.options)
            return;
        
        this.$elem = Z(this.elem);
        if (this.options.paste != "true")
        {//如果不支持粘贴
            this.$elem.on("paste", Z.E.forbidden);
        }
        else
        {//支持粘贴
            this.$elem.on("paste", this.onPaste, this);
        }
            
        //键点击双击,按下事件,按下恢复事件和值被修改事件
        this.$elem.click(this.onClick, this);
        this.$elem.dblclick(this.onDbClick, this);
        
        this.$elem.keypress(this.onKeyPress, this);
        this.$elem.keyup(this.onKeyUp, this);
        this.$elem.change(this.onChange, this);
        
        //禁止拖输入{dragenter:拖放到目标上面,dragleave:拖放出目标,drop:拖放执行}
        this.$elem.on("drop", Z.E.forbidden);
    },
    remove: function()
    {//删除
        if (this.options.paste != "true"){
            this.$elem.off("paste", Z.E.forbidden);
        }else{
            this.$elem.off("paste", this.onPaste, this);
        }
        this.$elem.offclick(this.onClick, this);
        this.$elem.offdblclick(this.onDbClick, this);
        this.$elem.offkeypress(this.onKeyPress, this);
        this.$elem.offkeyup(this.onKeyUp, this);
        this.$elem.offchange(this.onChange, this);
        this.$elem.off("drop", Z.E.forbidden);
    },
    
    /************************************************/
    //事件方法，设置三种控制方式：
    //1、键按下时判断是否可以输入，用is开头方法
    //2、键恢复时表示判断通过，用on再检查一次
    //3、由其他方式修改了值change事件时，用ch检查控制
    //4、由设置值方式修改值，不会触发change方法暂时没办法控制
    /************************************************/
    
    onClick: function(e)
    {//单击光标移到最后
        //this.$elem.focusEnd();
    },
    onDbClick: function(e)
    {//双击光标全部选中
        this.$elem.select();
    },
    onChange: function(e)
    {
        this.call("ch", e);
    },
    onKeyPress: function(e)
    {//键按下事件
        if (Z.E.isBackspace(e) || Z.E.isEnter(e) || Z.E.isCtrl(e))
        {//firefox退格键时也会触发,ie和chrome不会,如果按到Ctrl键不处理
            return;
        }
        this.call("is", e);
    },
    onKeyUp: function(e)
    {//键按下恢复事件
        if (Z.E.isBackspace(e) || Z.E.isEnter(e))
        {//firefox退格键时也会触发,ie和chrome不会
            return;
        }
        
        if (Z.E.isCtrl(e) && !Z.E.isCtrlV(e))
        {//按住Ctrl，但不是Ctrl+V不处理
            return;
        }
        
        this.call("on", e);
    },
    onPaste: function(e)
    {//支持粘贴,先填充，再设置2毫秒后处理
        setTimeout(Z.bind(this.onPasteTimout, this), 2, e);
    },
    onPasteTimout: function(e)
    {//粘贴后判断
        this.call("on", e);
    },
    call: function(action, e)
    {
        if (this.options.type && action+this.options.type in this){
            this[action+this.options.type].call(this, e);
        }
    },
    
    /************************************************/
    //数值型判断,替换和粘贴
    /************************************************/
    isNumeric: function(e)
    {//控制输入数值型
        var key = Z.E.key(e);
        if (!Z.V.isDigit(key))
            return Z.E.cancel(e);
    },
    onNumeric: function(e)
    {//处理非数值型数据
        var value = this.$elem.val();
        if (!/^[0-9]*$/.test(value))
        {
            value = value.replace(/[^0-9]/g, "");
            this.$elem.val(value);
        }
    },

    /************************************************/
    //整数型判断,替换和粘贴
    /************************************************/
    isInteger: function(e)
    {//不是数字和已输入0时后面不能再输入
        var key = Z.E.key(e);
        if (!Z.V.isDigit(key))
            return Z.E.cancel(e);
            
        var value = this.$elem.val();
        if (value == "0"){
            return Z.E.cancel(e);
        }
    },
    onInteger: function(e)
    {//处理非整数型数据
        var value = this.$elem.val();
        if (!/^[0-9]*$/.test(value)){
            value = value.replace(/[^0-9]/g, "");
        }
        
        value = Z.S.prefixZeroRemove(value);
        this.$elem.val(value);
    },
    
    /************************************************/
    //小数型判断,替换和粘贴
    /************************************************/
    isDecimal: function(e)
    {//控制输入小数型
        var key = Z.E.key(e);
        if (!Z.V.isDigitOrDot(key))
            return Z.E.cancel(e);
            
        if (!Z.V.isDot(key))
            return;
            
        var value = this.$elem.val();
        if (value.indexOf(".") != -1){
            return Z.E.cancel(e);
        }
    },
    onDecimal: function(e)
    {//处理非小数型数据
        var value = this.$elem.val();
        if (!/^[0-9.]*$/.test(value)){
            value = value.replace(/[^0-9.]/g, "");
        }
        
        //删除前缀0，第二个点后数据，如果首符是.则加为0.
        value = Z.S.prefixZeroRemove(value);
        value = Z.S.removeSecondDot(value);
        if (value.length > 0 && value.charAt(0) == '.'){
            value = "0" + value;
        }
            
        this.$elem.val(value);
    },
    chDecimal: function(e)
    {
        this.onDecimal(e);
        
        //小数最后一位是点号要去除
        var value = this.$elem.val();
        value = Z.S.removeAmountZero(value);
        this.$elem.val(value);
    },
    
    /************************************************/
    //字母型判断,替换和粘贴
    /************************************************/
    isAlphabetic: function(e)
    {//控制输入字母型
        var key = Z.E.key(e);
        if (!Z.V.isLetter(key))
            Z.E.cancel(e);
    },
    onAlphabetic: function(e)
    {//处理非字母型数据
        var value = this.$elem.val();
        if (!/^[a-zA-Z]*$/.test(value))
        {
            value = value.replace(/[^a-zA-Z]/g, "");
            this.$elem.val(value);
        }
    },
    
    /************************************************/
    //字母数值型判断,替换和粘贴
    /************************************************/
    isAlphaNumeric: function(e)
    {//控制输入字母数值型
        var key = Z.E.key(e);
        if (!Z.V.isLetter(key) && !Z.V.isDigit(key))
            Z.E.cancel(e);
    },
    onAlphabeticNumeric: function(e)
    {//处理非字母型数据
        var value = this.$elem.val();
        if (!/^[0-9a-zA-Z]*$/.test(value))
        {
            value = value.replace(/[^0-9a-zA-Z]/g, "");
            this.$elem.val(value);
        }
    },
    
    /************************************************/
    //2位小数的金额判断,替换和粘贴
    /************************************************/
    isAmount2R: function(e)
    {//控制输入2位小数金额
        var key = Z.E.key(e);
        if (!Z.V.isDigitOrDot(key))
            return Z.E.cancel(e);

        var isSelection = Z.EL.isSelection(this.$elem[0]);
        var value = this.$elem.val();
        if (Z.V.isDot(key))
        {//已有小数点也不允许再输入
            if (value.indexOf(".") != -1)
                return Z.E.cancel(e);
        }
        else
        {//控制小数点后最多两位小数，且不允许零后输零
            var ind = value.indexOf(".");
            if (ind != -1)
            {
                if (ind <= value.length-1-2 && !isSelection)//-1表示转为索引,-2表示两位小数
                    return Z.E.cancel(e);
            }
                
            if (value == "0" && key == 48)
                return Z.E.cancel(e);
        }
    },
    onAmount2R: function(e)
    {
        var value = this.$elem.val();
        if (!/^[0-9.]*$/.test(value)){
            value = value.replace(/[^0-9.]/g, "");
        }
        
        //删除前缀0，第二个点后数据，如果首符是.则加为0.
        value = Z.S.prefixZeroRemove(value);
        value = Z.S.removeSecondDot(value);
        if (value.length > 0 && value.charAt(0) == '.'){
            value = "0" + value;
        }
        
        //金额还要增加2位小数限制
        var ind = value.indexOf(".");
        if (ind != -1 && ind <= value.length-1-2){
            value = value.substring(0, ind+1+2);
        }
        this.$elem.val(value);
    },
    chAmount2R: function(e)
    {
        this.onAmount2R(e);
        
        //金额抹零
        var value = this.$elem.val();
        value = Z.S.removeAmountZero(value);
        this.$elem.val(value);
    },
    
    /************************************************/
    //折扣(0.01-10)判断,替换和粘贴
    /************************************************/
    isDiscount: function(e)
    {//是否是折扣
        var key = Z.E.key(e);
        if (!Z.V.isDigitOrDot(key))
            return Z.E.cancel(e);

        var isSelection = Z.EL.isSelection(this.$elem[0]);
            
        var value = this.$elem.val();
        if (value == "10" && !isSelection)
        {//如果值等于10不允许再输入
            return Z.E.cancel(e);
        }
            
        if (Z.V.isDot(key))
        {//已有小数点也不允许再输入
            if (value.indexOf(".") != -1 && !isSelection)
                return Z.E.cancel(e);
        }
        else
        {//控制折扣最大10折，小数点后最多两位小数
            if (value.length == 1)
            {
                if (value != 1 || key != 48)//0,2,3,4,5,6,7,8,9后面接数字要求转为如2后接数字转为2.3，1后面不是0也设置民1.
                    return this.$elem.val(value+".");
            }
            
            var ind = value.indexOf(".");
            if (ind != -1 && ind <= value.length-1-2 && !isSelection)//-1表示转为索引,-2表示两位小数
                return Z.E.cancel(e);
        }
    },
    onDiscount: function(e)
    {
        var value = this.$elem.val();
        if (!/^[0-9.]*$/.test(value)){
            value = value.replace(/[^0-9.]/g, "");
        }
            
        //删除前缀0，第二个点后数据，如果首符是.则加为0.
        value = Z.S.prefixZeroRemove(value);
        value = Z.S.removeSecondDot(value);
        if (value.length > 0 && value.charAt(0) == '.'){
            value = "0" + value;
        }
        
        //折扣还要增加2位小数限制
        var ind = value.indexOf(".");
        if (ind != -1 && ind <= value.length-1-2){
            value = value.substring(0, ind+1+2);
        }
        
        //再比较不允许大于10,大于10则置空
        this.$elem.val((parseFloat(value) > 10)?"":value);
    },
    chDiscount: function(e)
    {
        this.onDiscount(e);
        
        //打折抹零
        var value = this.$elem.val();
        value = Z.S.removeAmountZero(value);
        this.$elem.val(value);
    },
    
    /************************************************/
    //日期(yyyy-MM-dd)判断,替换和粘贴
    /************************************************/
    isDate: function(e)
    {//是否是小时:分钟
        var key = Z.E.key(e);
        if (!Z.V.isDigitOrMinus(key))
            return Z.E.cancel(e);

        var isSelection = Z.EL.isSelection(this.$elem[0]);
        var value = this.$elem.val();
        if (value.length >= 10 && !isSelection)
            return Z.E.cancel(e);
            
        var regexp = null;
        switch(value.length)
        {
            case 0:regexp = /^[0-9]$/;break;
            case 1:regexp = /^[0-9]{2}$/;break;
            case 2:regexp = /^[0-9]{3}$/;break;
            case 3:regexp = /^[0-9]{4}$/;break;
            case 4:regexp = /^[0-9]{4}\-$/;break;
            case 5:regexp = /^[0-9]{4}\-[0-1]$/;break;
            case 6:regexp = /^[0-9]{4}\-(0[1-9]|1[0-2])$/;break;
            case 7:regexp = /^[0-9]{4}\-(0[1-9]|1[0-2])\-$/;break;
            case 8:regexp = /^[0-9]{4}\-(0[1-9]|1[0-2])\-[0-3]$/;break;
            case 9:
            case 10:regexp = Z.R.DATE;break;
            default:return Z.E.cancel(e);
        }

        if (value.length < 10)
            value += String.fromCharCode(key);
        if (!regexp.test(value))
            return Z.E.cancel(e);
    },
    onDate: function(e)
    {
        var value = this.$elem.val();
        if (!/^[0-9\-]*$/.test(value))
            value = value.replace(/[^0-9\-]/g, "");
            
        //再比较是否有效，有效则加入，否则置空
        var regexp = null;
        switch(value.length)
        {
            case 1:regexp = /^[0-9]$/;break;
            case 2:regexp = /^[0-9]{2}$/;break;
            case 3:regexp = /^[0-9]{3}$/;break;
            case 4:regexp = /^[0-9]{4}$/;break;
            case 5:regexp = /^[0-9]{4}\-$/;break;
            case 6:regexp = /^[0-9]{4}\-[0-1]$/;break;
            case 7:regexp = /^[0-9]{4}\-(0[1-9]|1[0-2])$/;break;
            case 8:regexp = /^[0-9]{4}\-(0[1-9]|1[0-2])\-$/;break;
            case 9:regexp = /^[0-9]{4}\-(0[1-9]|1[0-2])\-[0-3]$/;break;
            case 10:regexp = Z.R.DATE;break;
        }
        
        //再比较是否有效，有效则加入，否则置空
        this.$elem.val((!regexp || !regexp.test(value))?"":value);
    },
    
    /************************************************/
    //小时分钟(00:00)判断,替换和粘贴
    /************************************************/
    isHourMinute: function(e)
    {//是否是小时:分钟
        var key = Z.E.key(e);
        if (!Z.V.isDigitOrColon(key))
            return Z.E.cancel(e);

        var isSelection = Z.EL.isSelection(this.$elem[0]);
        var value = this.$elem.val();
        if (value.length >= 5 && !isSelection)
            return Z.E.cancel(e);
            
        var regexp = null;
        switch(value.length)
        {
            case 0:regexp = /^[0-2]$/;break;
            case 1:regexp = /^([0-1][0-9]|[2][0-3])$/;break;
            case 2:regexp = /^([0-1][0-9]|[2][0-3]):$/;break;
            case 3:regexp = /^([0-1][0-9]|[2][0-3]):([0-5])$/;break;
            case 4:
            case 5:regexp = /^([0-1][0-9]|[2][0-3]):([0-5][0-9])$/;break;
            default:return Z.E.cancel(e);
        }

        if (value.length < 5)
            value += String.fromCharCode(key);
        if (!regexp.test(value))
            return Z.E.cancel(e);
    },
    onHourMinute: function(e)
    {
        var value = this.$elem.val();
        if (!/^[0-9:]*$/.test(value))
            value = value.replace(/[^0-9:]/g, "");
            
        //再比较是否有效，有效则加入，否则置空
        var regexp = null;
        switch(value.length)
        {
            case 1:regexp = /^[0-2]$/;break;
            case 2:regexp = /^([0-1][0-9]|[2][0-3])$/;break;
            case 3:regexp = /^([0-1][0-9]|[2][0-3]):$/;break;
            case 4:regexp = /^([0-1][0-9]|[2][0-3]):([0-5])$/;break;
            case 5:regexp = /^([0-1][0-9]|[2][0-3]):([0-5][0-9])$/;break;
        }
        
        //再比较是否有效，有效则加入，否则置空
        this.$elem.val((!regexp || !regexp.test(value))?"":value);
    }
}

Z.Input.load = function(target)
{//加载函数
    //如果传入了目标，则在目标中查找，否则查找全部
    Z.$selector("input", target).each(function(elem)
    {
        if (Z.B.msie)
        {//IE处理成灰色和主流一致
            Z.placeholder(elem);
        }
        
        if (Z.EL.get(elem, "readonly") != null)
        {//如果有只读属性时不响应回退等按键,注意element里有readonly属性,默认=null
            Z.E.add(elem, "keydown", Z.E.forbidden);
            return;
        }
        
        if (!Z.EL.has(elem, "data-options"))
            return;
        
        //解析表达式并放置到哈唏表中
        var expression = Z.EL.get(elem, "data-options");
        var options = Z.AR.toObject(expression, ";");
        if (!options.type || !Z.AR.contains(Z.Input.types, options.type))
        {//不支持的类型不处理
            return;
        }
        
        //关闭输入法,chrome不支持,ie和firefox支持
        Z.EL.addClass(elem, "z-ime-disabled");
        new Z.Input({elem: elem, options: options});
    });
};

Z.onload(Z.Input.load);


/******************************************************/
//支持button组之间点击切换active
/******************************************************/
Z.ButtonGroup = {};
Z.ButtonGroup.map = new Z.HashMap();
Z.ButtonGroup.load = function(target)
{//加载
    //1.先清除以前的缓存
    if (target == null)
        Z.ButtonGroup.map.clear();
    
    //2.查找到符合条件的加到缓存
    var elements = Z.$selector("button", target);
    if (!elements || elements.length == 0)
        return;
        
    Z.each(elements, function(elem)
    {
        var group = Z.ButtonGroup.getGroupName(elem);
        if (!group){
            return;
        }
        
        if (!Z.ButtonGroup.map.containsKey(group))
            Z.ButtonGroup.map.put(group, [elem]);
        else
            Z.ButtonGroup.map.get(group).push(elem);
        
        Z(elem).click(Z.ButtonGroup.onclick);
    });
};

Z.ButtonGroup.getGroupName = function(elem)
{//获取组名
    if (!Z.EL.has(elem, "data-options"))
        return null;
        
    var expression = Z.EL.get(elem, "data-options");
    var options = Z.AR.toObject(expression, ";");
    return options.group;
};

Z.ButtonGroup.onclick = function(e)
{//点击事件
    var elem = Z.E.current(e);
    var group = Z.ButtonGroup.getGroupName(elem);
    if (!group){
        return;
    }
        
    Z.each(Z.ButtonGroup.map.get(group), function(btn){
        Z(btn).removeClass("z-active");
    });
    
    Z(elem).addClass("z-active");
}

Z.onload(Z.ButtonGroup.load);


/******************************************************/
//支持radio变成.radio,并支持点击切换active
/******************************************************/
Z.Radio = function(e)
{
    var $input = this;
    var clickFun = $input.onclick;
    if (typeof clickFun === 'function')
    {
        var oldCheck = $input.checked;
        var clickDone = true;
        $input.click();
        if (oldCheck === $input.checked){
            return;
        }
    }
    
    var $role = Z(Z.E.current(e));
    var name = Z.S.trim($role.attr("data-name"));
    var doThisTrue = function()
    {
        if (!Z.V.isEmpty(name))
        {//如果名称不为空，则把相同名称的都关掉
            Z("input[type=radio][name="+name+"]").attr("checked", false);
            Z("i.z-radio[data-name="+name+"]").removeClass("z-active");
        }
        $input.checked = true;
        $role.addClass("z-active");
    }
    
    //设置当前状态
    if (clickDone)
    {
        if($input.checked) {
            doThisTrue();
        } else {
            $role.removeClass("z-active");
        }
    }
    else
    {    
        doThisTrue();
        if ($input.onchange){
            $input.onchange();
        }
    }
};

Z.Radio.load = function(target)
{
    Z.$selector(".z-role-radio", target).each(function(elem)
    {//先删除目标范围内的数据
        Z(elem).remove(); 
    });
    
    Z.$selector("input[type=radio][data-role=z-radio]", target).each(function(elem)
    {//再加载目标范围内的数据
        var random = "Z_Radio_"+Z.random(10);
        var $elem = Z(elem).hidden().attr("data-id", random);
        var $cover = Z.$cover($elem).on('click', Z.E.stop);
        
        var width = $elem.offsetWidth();
        var id = Z.S.trim($elem.attr("id"));
        var name = Z.S.trim($elem.attr("name"));
        var checked = Z.S.trim($elem.attr("checked"));
        var classes = (checked == "true"?"z-active ":"") + Z.S.trim($elem.attr("data-class"));
        
        //新建.radio替换原来的radio，并设置name,data-class和点击事件
        var $role = Z('<i class="z-radio z-role-radio"></i>').appendTo($cover)
            .cssMaybe("padding-left", $elem.css("paddingLeft"))
            .cssMaybe("padding-right", $elem.css("paddingRight"))
            .cssMaybe("padding-top", $elem.css("paddingTop"))
            .cssMaybe("padding-bottom", $elem.css("paddingBottom"))
            .addClass("z-relative").css("margin-left", -width).addClass(classes)
            .attr("id", random).attr("data-id", id).attr("data-name", name)
            .click(Z.Radio, elem);
    });
};

Z.Radio.setChecked = function(elem, val)
{
    var $elem = Z.$elem(elem, "Z.Radio.setChecked");
    
    $elem = Z($elem[0]);
    
    var elemType = $elem.attr('type');
    if (!elemType || elemType.trim().toLowerCase() !== 'radio')
        return Z.alert('[Z.Radio.setChecked]参数[elem]对象类型为radio！');
        
    if (typeof val !== 'boolean')
        return Z.alert('[Z.Radio.setChecked]第二个参数必须是布尔值！');
    
    //同组radio
    var radioName = Z.S.trim($elem.attr("name"));
    if (val && !Z.V.isEmpty(radioName))
    {
        Z("input[type=radio][name="+radioName+"]").attr("checked", false);
        Z("i.z-radio[data-name="+radioName+"]").removeClass("z-active");
    }
    $elem.attr("checked", val);
    
    //Z样式修改
    var dataRole = $elem.attr("data-role");
    var $role = $elem.parent().find('i.z-radio');
    if (!dataRole || dataRole !== "z-radio" || !$role[0])
        return;
    
    if (val)
        $role.addClass("z-active");
    else
        $role.removeClass("z-active");
}

Z.onload(Z.Radio.load);


/******************************************************/
//支持checkbox变成.checkbox,并支持点击切换active
/******************************************************/
Z.Checkbox = function(e)
{
    var $input = this;
    var clickFun = $input.onclick;
    if (typeof clickFun === 'function')
    {
        var oldCheck = $input.checked;
        var clickDone = true;
        $input.click();
        if (oldCheck === $input.checked){
            return;
        }
    }

    var $role = Z(Z.E.current(e));
    var checked = $role.hasClass("z-active");
    
    //设置当前状态
    if (clickDone)
    {
        if($input.checked) {
            $role.addClass("z-active");
        } else {
            $role.removeClass("z-active");
        }
    }
    else
    {
        //切换active
        $input.checked = !checked;
        $role.toggleClass("z-active");
        if ($input.onchange){
            $input.onchange();
        }
    }
};

Z.Checkbox.load = function(target)
{
    Z.$selector(".z-role-checkbox", target).each(function(elem)
    {//先删除目标范围内的数据
        Z(elem).remove(); 
    });
    
    Z.$selector("input[type=checkbox][data-role=z-checkbox]", target).each(function(elem)
    {//再加载目标范围内的数据
        var random = "Z_Checkbox_"+Z.random(10);
        var $elem = Z(elem).hidden().attr("data-id", random);
        var $cover = Z.$cover($elem).on('click', Z.E.stop);
        
        var width = $elem.offsetWidth();
        var id = Z.S.trim($elem.attr("id"));
        var name = Z.S.trim($elem.attr("name"))
        var checked = Z.S.trim($elem.attr("checked"));
        var classes = (checked == "true"?"z-active ":"") + Z.S.trim($elem.attr("data-class"));
        
        //新建.checkbox替换原来的checkbox，并设置name,data-class和点击事件
        var $role = Z('<i class="z-checkbox z-role-checkbox"></i>').appendTo($cover)
            .cssMaybe("padding-left", $elem.css("paddingLeft"))
            .cssMaybe("padding-right", $elem.css("paddingRight"))
            .cssMaybe("padding-top", $elem.css("paddingTop"))
            .cssMaybe("padding-bottom", $elem.css("paddingBottom"))
            .addClass("z-relative").css("margin-left", -width).addClass(classes)
            .attr("id", random).attr("data-id", id).attr("data-name", name)
            .click(Z.Checkbox, elem);
    });
};

Z.Checkbox.click = function(role)
{
    var $role = Z.$elem(role, "Z.Checkbox.click");
    var $elem = Z("input[type=checkbox][data-role=z-checkbox][data-id="+$role.attr("id")+"]");
    
    //切换active
    var checked = $role.hasClass("z-active");
    $role.toggleClass("z-active");
    $elem.attr("checked", !checked);
    
    if ($elem[0].onchange){
        $elem[0].onchange();
    }
};

Z.Checkbox.setChecked = function(elem, val)
{
    var $$elem = Z.$elem(elem, "Z.Checkbox.setChecked");
    var inputLength = $$elem.length;
    var $$checkBox = Z("");
    var i = 0, j = 0, $elem, elemType;
    for (i;i < inputLength;i++)
    {
        $elem = $$elem[i];
        elemType = Z($elem).attr('type');
        if (elemType && elemType.trim().toLowerCase() === 'checkbox')
        {
            $$checkBox[j] = $elem;
            j++;
        }
    }
    inputLength = j;
    if (inputLength === 0)
        return Z.alert('[Z.Checkbox.setChecked]参数[elem]对象类型为checkbox！');
    
    if (typeof val !== 'boolean')
        return Z.alert('[Z.Checkbox.setChecked]第二个参数必须是布尔值！');
    
    var dataRole, $role;
    for (i = 0;i < inputLength;i++)
    {
        $elem = Z($$checkBox[i]);
        $elem.attr('checked', val);
        
        dataRole = $elem.attr("data-role");
        $role = $elem.parent().find('i.z-checkbox');
        if (!dataRole || dataRole !== "z-checkbox" || !$role[0])
            continue;
            
        if (val)
            $role.addClass("z-active");
        else
            $role.removeClass("z-active");
    }
    
}

Z.onload(Z.Checkbox.load);

/******************************************************/
//支持textarea的maxlength和placeholder
/******************************************************/

Z.Textarea = {};
Z.Textarea.load = function(target)
{//加载函数
    //如果传入了目标，则在目标中查找，否则查找全部
    Z.$selector("textarea", target).each(function(elem)
    {
        var $elem = Z(elem);
        
        //1.检查placeholder
        if (Z.B.msie || $elem.attr("data-role") == "z-placeholder")
        {//IE处理成灰色和主流一致，指定了要求处理的描述
            Z.placeholder(elem);
        }
        
        //2.检查maxlength
        var maxlength = $elem.attr("maxlength");
        if (Z.V.isInteger(maxlength))
        {
            maxlength = parseInt(maxlength);
            $elem.keypress = function(e)
            {//键按下事件
                if (Z.E.isBackspace(e) || Z.E.isEnter(e) || Z.E.isCtrl(e))
                {//firefox退格键时也会触发,ie和chrome不会,如果按到Ctrl键不处理
                    return;
                }
                if ($elem.val().length >= maxlength)
                {
                    return Z.E.cancel(e);
                }
            }
        }
    });
};

Z.onload(Z.Textarea.load);

/******************************************************/
//支持form使用iframe调用
/******************************************************/
Z.CallFrame = {};
Z.CallFrame.load = function()
{
    Z("form[data-role=z-call-frame]").each(function(form)
    {
        //1.先判断是否存在<iframe name="zCallFrame"></iframe>
        var $frame = Z('iframe[name="zCallFrame"]');
        if ($frame.length == 0)
            $frame = Z('<iframe name="zCallFrame" style="display:none;"></iframe>').prependTo("body");
            
        //2.设置form的target
        form.target = "zCallFrame";
        
        //3.设置zFormIndex
        if (!form.zFormIndex)
        {
            var zFormIndex = document.createElement("input");
            zFormIndex.name = "zFormIndex";
            zFormIndex.type = "hidden";
            form.insertBefore(zFormIndex, form.firstNode);
        }
        var ind = -1;
        for (var i=0;i<document.forms.length;i++)
        {
            if (form == document.forms[i])
            {
                ind = i;
                break;
            }
        }
        form.zFormIndex.value = ind;
        
        //4.设置zCallFrame
        if (!form.zCallFrame)
        {
            var zCallFrame = document.createElement("input");
            zCallFrame.name = "zCallFrame";
            zCallFrame.type = "hidden";
            form.insertBefore(zCallFrame, form.firstNode);
        }
        form.zCallFrame.value = "true";
    });
};

Z.onload(Z.CallFrame.load);

/*************************************************************************************/
//描述对象
/*************************************************************************************/
Z.placeholder = function(elem)
{
    var $elem = Z.$elem(elem);
    var ph = $elem.attr("placeholder");
    if (Z.V.isEmptyBlank(ph))
        return;
    
    $elem.removeAttr("placeholder");
    var width = $elem.offsetWidth();
    var height = $elem.offsetHeight();

    //创建一个封套把input/textarea和placeholder包含在一起
    var $cover = Z.$cover($elem);
    
    //创建描述对象
    var $placeholder = Z('<div class="z-placeholder">'+ph+'</div>');
    $placeholder.appendTo($cover)
                .opacity(0.8)
                .css({width: width, height: height})
                .cssMaybe("padding-left", $elem.cssNum("paddingLeft")+2)//保留光标2像素位置
                .cssMaybe("padding-right", $elem.css("paddingRight"))
                .cssMaybe("padding-top", $elem.css("paddingTop"))
                .cssMaybe("padding-bottom", $elem.css("paddingBottom"))
                .cssMaybe("font-family", $elem.css("fontFamily"))
                .cssMaybe("font-size", $elem.css("fontSize"))
                .cssMaybe("line-height", $elem.css("lineHeight"))
                .cssMaybe("text-indent", $elem.css("textIndent"));
                
    if ($elem.val().length > 0){
        $placeholder.hide();
    }

    //事件隐藏和显示描述
    $elem.keydown(function(){$placeholder.hide();});
    $elem.keyup(function()
    {
        if ($elem.val().length > 0)
            $placeholder.hide();
        else
            $placeholder.show();
    });
}

/*************************************************************************************/
//<pre>对象
/*************************************************************************************/
Z.preRemoveBR = function()
{//定义了.z-text-prewrap和.z-text-preline样式且不是pre标签的首字符\n删除
    Z(".z-text-preline:not(pre),.z-text-prewrap:not(pre)").each(function(elem)
    {
        var $elem = Z(elem);
        var html = $elem.html();
        if (Z.V.isEmpty(html))
            return;
            
        if (html.charAt(0) == '\n'){
            $elem.html(html.substring(1));
        }
    });
}

Z.onload(Z.preRemoveBR);

//END
})(zhiqim);